1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.forces.gravity.potential;
18
19 import java.io.IOException;
20 import java.io.InputStream;
21 import java.text.ParseException;
22 import java.util.ArrayList;
23 import java.util.Arrays;
24 import java.util.List;
25 import java.util.Locale;
26
27 import org.hipparchus.util.FastMath;
28 import org.hipparchus.util.Precision;
29 import org.orekit.data.DataLoader;
30 import org.orekit.errors.OrekitException;
31 import org.orekit.errors.OrekitMessages;
32
33
34
35
36
37
38
39
40
41
42
43
44 public abstract class PotentialCoefficientsReader implements DataLoader {
45
46
47 private int maxParseDegree;
48
49
50 private int maxParseOrder;
51
52
53 private final String supportedNames;
54
55
56 private final boolean missingCoefficientsAllowed;
57
58
59 private boolean readComplete;
60
61
62 private double ae;
63
64
65 private double mu;
66
67
68 private double[][] rawC;
69
70
71 private double[][] rawS;
72
73
74 private boolean normalized;
75
76
77 private TideSystem tideSystem;
78
79
80
81
82
83
84 protected PotentialCoefficientsReader(final String supportedNames,
85 final boolean missingCoefficientsAllowed) {
86 this.supportedNames = supportedNames;
87 this.missingCoefficientsAllowed = missingCoefficientsAllowed;
88 this.maxParseDegree = Integer.MAX_VALUE;
89 this.maxParseOrder = Integer.MAX_VALUE;
90 this.readComplete = false;
91 this.ae = Double.NaN;
92 this.mu = Double.NaN;
93 this.rawC = null;
94 this.rawS = null;
95 this.normalized = false;
96 this.tideSystem = TideSystem.UNKNOWN;
97 }
98
99
100
101
102 public String getSupportedNames() {
103 return supportedNames;
104 }
105
106
107
108
109 public boolean missingCoefficientsAllowed() {
110 return missingCoefficientsAllowed;
111 }
112
113
114
115
116
117
118 public void setMaxParseDegree(final int maxParseDegree) {
119 this.maxParseDegree = maxParseDegree;
120 }
121
122
123
124
125
126 public int getMaxParseDegree() {
127 return maxParseDegree;
128 }
129
130
131
132
133
134
135 public void setMaxParseOrder(final int maxParseOrder) {
136 this.maxParseOrder = maxParseOrder;
137 }
138
139
140
141
142
143 public int getMaxParseOrder() {
144 return maxParseOrder;
145 }
146
147
148 public boolean stillAcceptsData() {
149 return !(readComplete &&
150 getMaxAvailableDegree() >= getMaxParseDegree() &&
151 getMaxAvailableOrder() >= getMaxParseOrder());
152 }
153
154
155
156
157 protected void setReadComplete(final boolean readComplete) {
158 this.readComplete = readComplete;
159 }
160
161
162
163
164 protected void setAe(final double ae) {
165 this.ae = ae;
166 }
167
168
169
170
171 protected double getAe() {
172 return ae;
173 }
174
175
176
177
178 protected void setMu(final double mu) {
179 this.mu = mu;
180 }
181
182
183
184
185 protected double getMu() {
186 return mu;
187 }
188
189
190
191
192 protected void setTideSystem(final TideSystem tideSystem) {
193 this.tideSystem = tideSystem;
194 }
195
196
197
198
199 protected TideSystem getTideSystem() {
200 return tideSystem;
201 }
202
203
204
205
206
207
208
209
210
211
212 protected void setRawCoefficients(final boolean rawNormalized,
213 final double[][] c, final double[][] s,
214 final String name)
215 throws OrekitException {
216
217
218 normalized = rawNormalized;
219
220
221
222
223
224
225 setIfUnset(c, 0, 0, 1);
226 setIfUnset(s, 0, 0, 0);
227
228
229 setIfUnset(c, 1, 0, 0);
230 setIfUnset(s, 1, 0, 0);
231 setIfUnset(c, 1, 1, 0);
232 setIfUnset(s, 1, 1, 0);
233
234
235 for (int i = 0; i < c.length; ++i) {
236 for (int j = 0; j < c[i].length; ++j) {
237 if (Double.isNaN(c[i][j])) {
238 throw new OrekitException(OrekitMessages.MISSING_GRAVITY_FIELD_COEFFICIENT_IN_FILE,
239 'C', i, j, name);
240 }
241 }
242 }
243 rawC = c;
244
245
246 for (int i = 0; i < s.length; ++i) {
247 for (int j = 0; j < s[i].length; ++j) {
248 if (Double.isNaN(s[i][j])) {
249 throw new OrekitException(OrekitMessages.MISSING_GRAVITY_FIELD_COEFFICIENT_IN_FILE,
250 'S', i, j, name);
251 }
252 }
253 }
254 rawS = s;
255
256 }
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275 private boolean setIfUnset(final double[][] array,
276 final int i,
277 final int j,
278 final double value) {
279 if (array.length > i && array[i].length > j &&
280 (Double.isNaN(array[i][j]) || Precision.equals(array[i][j], 0.0, 0))) {
281
282 array[i][j] = value;
283 return true;
284 } else {
285 return false;
286 }
287 }
288
289
290
291
292
293 public int getMaxAvailableDegree() {
294 return rawC.length - 1;
295 }
296
297
298
299
300
301 public int getMaxAvailableOrder() {
302 return rawC[rawC.length - 1].length - 1;
303 }
304
305
306 public abstract void loadData(InputStream input, String name)
307 throws IOException, ParseException, OrekitException;
308
309
310
311
312
313
314
315
316
317
318
319
320 public abstract RawSphericalHarmonicsProvider getProvider(boolean wantNormalized, int degree, int order)
321 throws OrekitException;
322
323
324
325
326
327
328
329
330
331
332
333
334 protected ConstantSphericalHarmonics getConstantProvider(final boolean wantNormalized,
335 final int degree, final int order)
336 throws OrekitException {
337
338 if (!readComplete) {
339 throw new OrekitException(OrekitMessages.NO_GRAVITY_FIELD_DATA_LOADED);
340 }
341
342 if (degree >= rawC.length) {
343 throw new OrekitException(OrekitMessages.TOO_LARGE_DEGREE_FOR_GRAVITY_FIELD,
344 degree, rawC.length - 1);
345 }
346
347 if (order >= rawC[rawC.length - 1].length) {
348 throw new OrekitException(OrekitMessages.TOO_LARGE_ORDER_FOR_GRAVITY_FIELD,
349 order, rawC[rawC.length - 1].length);
350 }
351
352
353 final double[][] truncatedC = buildTriangularArray(degree, order, 0.0);
354 final double[][] truncatedS = buildTriangularArray(degree, order, 0.0);
355 rescale(1.0, normalized, rawC, rawS, wantNormalized, truncatedC, truncatedS);
356
357 return new ConstantSphericalHarmonics(ae, mu, tideSystem, truncatedC, truncatedS);
358
359 }
360
361
362
363
364
365
366
367 protected static double[][] buildTriangularArray(final int degree, final int order, final double value) {
368 final int rows = degree + 1;
369 final double[][] array = new double[rows][];
370 for (int k = 0; k < array.length; ++k) {
371 array[k] = buildRow(k, order, value);
372 }
373 return array;
374 }
375
376
377
378
379
380
381
382
383 protected static double parseDouble(final String string) {
384 return Double.parseDouble(string.toUpperCase(Locale.ENGLISH).replace('D', 'E'));
385 }
386
387
388
389
390
391
392
393 protected static double[] buildRow(final int degree, final int order, final double value) {
394 final double[] row = new double[FastMath.min(order, degree) + 1];
395 Arrays.fill(row, value);
396 return row;
397 }
398
399
400
401
402
403
404
405 protected void extendListOfLists(final List<List<Double>> list, final int degree, final int order,
406 final double value) {
407 for (int i = list.size(); i <= degree; ++i) {
408 list.add(new ArrayList<Double>());
409 }
410 final List<Double> listN = list.get(degree);
411 final Double v = Double.valueOf(value);
412 for (int j = listN.size(); j <= order; ++j) {
413 listN.add(v);
414 }
415 }
416
417
418
419
420
421 protected double[][] toArray(final List<List<Double>> list) {
422 final double[][] array = new double[list.size()][];
423 for (int i = 0; i < array.length; ++i) {
424 array[i] = new double[list.get(i).size()];
425 for (int j = 0; j < array[i].length; ++j) {
426 array[i][j] = list.get(i).get(j);
427 }
428 }
429 return array;
430 }
431
432
433
434
435
436
437
438
439
440
441 protected void parseCoefficient(final String field, final List<List<Double>> list,
442 final int i, final int j,
443 final String cName, final String name)
444 throws OrekitException {
445 final double value = parseDouble(field);
446 final double oldValue = list.get(i).get(j);
447 if (Double.isNaN(oldValue) || Precision.equals(oldValue, 0.0, 0)) {
448
449 list.get(i).set(j, value);
450 } else {
451 throw new OrekitException(OrekitMessages.DUPLICATED_GRAVITY_FIELD_COEFFICIENT_IN_FILE,
452 name, i, j, name);
453 }
454 }
455
456
457
458
459
460
461
462
463
464
465 protected void parseCoefficient(final String field, final double[][] array,
466 final int i, final int j,
467 final String cName, final String name)
468 throws OrekitException {
469 final double value = parseDouble(field);
470 final double oldValue = array[i][j];
471 if (Double.isNaN(oldValue) || Precision.equals(oldValue, 0.0, 0)) {
472
473 array[i][j] = value;
474 } else {
475 throw new OrekitException(OrekitMessages.DUPLICATED_GRAVITY_FIELD_COEFFICIENT_IN_FILE,
476 name, i, j, name);
477 }
478 }
479
480
481
482
483
484
485
486
487
488
489
490
491 protected static void rescale(final double scale,
492 final boolean normalizedOrigin, final double[][] originC,
493 final double[][] originS, final boolean wantNormalized,
494 final double[][] rescaledC, final double[][] rescaledS)
495 throws OrekitException {
496
497 if (wantNormalized == normalizedOrigin) {
498
499 for (int i = 0; i < rescaledC.length; ++i) {
500 final double[] rCi = rescaledC[i];
501 final double[] rSi = rescaledS[i];
502 final double[] oCi = originC[i];
503 final double[] oSi = originS[i];
504 for (int j = 0; j < rCi.length; ++j) {
505 rCi[j] = oCi[j] * scale;
506 rSi[j] = oSi[j] * scale;
507 }
508 }
509 } else {
510
511
512
513
514
515 final double[][] factors = GravityFieldFactory.getUnnormalizationFactors(rescaledC.length - 1,
516 rescaledC.length - 1);
517
518 if (wantNormalized) {
519
520 for (int i = 0; i < rescaledC.length; ++i) {
521 final double[] rCi = rescaledC[i];
522 final double[] rSi = rescaledS[i];
523 final double[] oCi = originC[i];
524 final double[] oSi = originS[i];
525 final double[] fi = factors[i];
526 for (int j = 0; j < rCi.length; ++j) {
527 final double factor = scale / fi[j];
528 rCi[j] = oCi[j] * factor;
529 rSi[j] = oSi[j] * factor;
530 }
531 }
532 } else {
533
534 for (int i = 0; i < rescaledC.length; ++i) {
535 final double[] rCi = rescaledC[i];
536 final double[] rSi = rescaledS[i];
537 final double[] oCi = originC[i];
538 final double[] oSi = originS[i];
539 final double[] fi = factors[i];
540 for (int j = 0; j < rCi.length; ++j) {
541 final double factor = scale * fi[j];
542 rCi[j] = oCi[j] * factor;
543 rSi[j] = oSi[j] * factor;
544 }
545 }
546 }
547
548 }
549 }
550
551 }